//
//  JCUIPredicateFormat
//
//  Created by Chuan on 2021/2/1.
//  Copyright © 2021 Chuan. All rights reserved.
//

import Foundation

public extension NSPredicate {
    
    class func establish2(_ p: JCUIPredicateFormat) -> NSPredicate {
        return NSPredicate(format: p.format)
    }
}

public struct JCUIPredicateFormat {
    public enum Comparison {
        case equle(_ value: Any)
        case notEqule(_ value: Any)
        case lessThan(_ value: Any)
        case lessThanOrEqual(_ value: Any)
        case greaterThan(_ value: Any)
        case greaterThanOrEqual(_ value: Any)
        case between(_ lower: Any, _ upper: Any)
        case line(_ value: String)
        case beginSwith(_ value: String)
        case endSwith(_ value: String)
        case contains(_ value: String)
        case matches(_ value: String)
        case `in`(_ value: [Any])
    }
    
    fileprivate var format: String
    
    init(key: String, comparison: Comparison) {
        switch comparison {
        case .equle(let value):
            self.format = key + " == \(value)"
        case .notEqule(let value):
            self.format = key + " != \(value)"
        case .lessThan(let value):
            self.format = key + " < \(value)"
        case .lessThanOrEqual(let value):
            self.format = key + " <= \(value)"
        case .greaterThan(let value):
            self.format = key + " > \(value)"
        case .greaterThanOrEqual(let value):
            self.format = key + " >= \(value)"
        case .between(let lower, let upper):
            self.format = key + " BETWEEN {\(lower), \(upper)}"
        case .line(let value):
            self.format = key + " LIKE[c] \'\(value)\'"
        case .beginSwith(let value):
            self.format = key + " BEGINSWITH[c] '\(value)'"
        case .endSwith(let value):
            self.format = key + " ENDSWITH[c] '\(value)'"
        case .contains(let value):
            self.format = key + " CONTAINS[c] '\(value)'"
        case .matches(let value):
            self.format = key + "MATCHES \(value)"
        case .in(let value):
            self.format = key + " IN {\(value)}"
        }
    }
    
    fileprivate init(format: String) {
        self.format = format
    }
    
    static func SELF(_ comparison: Comparison) -> JCUIPredicateFormat {
        return JCUIPredicateFormat(key: "SELF", comparison: comparison)
    }
    
    static func key(_ key: String, _ comparison: Comparison) -> JCUIPredicateFormat {
        return JCUIPredicateFormat(key: key, comparison: comparison)
    }
}

public extension JCUIPredicateFormat {
    
    static func && (lhs: JCUIPredicateFormat, rhs: JCUIPredicateFormat) -> JCUIPredicateFormat {
        return JCUIPredicateFormat(format: "\(lhs.format) AND \(rhs.format)")
    }
    
    static func || (lhs: JCUIPredicateFormat, rhs: JCUIPredicateFormat) -> JCUIPredicateFormat {
        return JCUIPredicateFormat(format: "\(lhs.format) OR \(rhs.format)")
    }
    
    static prefix func !(rhs: JCUIPredicateFormat) -> JCUIPredicateFormat {
        return JCUIPredicateFormat(format: "NOT (\(rhs.format)")
    }
}
